package com.leyou.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.leyou.api.R;
import com.leyou.common.constant.SkuEnum;
import com.leyou.common.page.PageResult;
import com.leyou.common.to.Goods;
import com.leyou.common.to.Specs;
import com.leyou.common.to.skuto;
import com.leyou.entity.*;
import com.leyou.feign.EsGoodsFeign;
import com.leyou.service.*;
import com.leyou.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;


import com.leyou.dao.SpuDao;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;


@Service("spuService")
@Transactional
@Slf4j
public class SpuServiceImpl extends ServiceImpl<SpuDao, SpuEntity> implements SpuService {

    @Resource
    SpuDao spuDao;

    @Autowired
    SpuDetailService spuDetailService;

    @Autowired
    SkuService skuService;

    @Autowired
    StockService stockService;

    @Resource
    EsGoodsFeign goodsFeign;

    @Autowired
    BrandService brandService;

    @Autowired
    CategoryService categoryService;

    @Autowired
    SpecParamService paramService;


    /**
     * 删除商品 TODO  1.删除spu表信息  2.删除sku表信息 3.删除库存表信息 4.删除商品简介表  5.删除es中保存的信息
     * @param id
     */
    @Override
    public void deleteProduct(Long id) {
        this.removeById(id);
    }

    /**
     * 上下架商品
     * @param saleable
     * @param id
     */
    @Override
    public void SaveSaleable(Long saleable, Long id) {

        if(saleable != 1){
            // 调用远程商品上架功能 将商品数据存入es中
            //  Goods
            Goods goods = new Goods();
            //  1根据商品的spuid 获取spu信息
            SpuEntity spu = this.getById(id);
            BeanUtils.copyProperties(spu,goods);
            //  2. 根据品牌id 获取品牌的详细信息
            BrandEntity brandEntity = brandService.getById(spu.getBrandId());
            if(brandEntity != null){
                goods.setBrandId(brandEntity.getId());
                goods.setBrandImg(brandEntity.getImage());
                goods.setBrandName(brandEntity.getName());
            }
            // 3.设置检索字段值
            String cname = categoryService.getCategoryAllNameByid(spu.getCid1(), spu.getCid2(), spu.getCid3());
            String[] split = cname.split("/");
            goods.setAll(spu.getTitle()+" "+brandEntity.getName()+" "+split[0]+" "+split[1]+" "+split[2]);  //  包含 标题，分类，甚至品牌
            goods.setCatelog3Name(split[2]);
            goods.setCatelog2Name(split[1]);
            goods.setCatelog1Name(split[0]);
            // 4.设置商品创建时间  放遍做排序
            goods.setCreateTime(spu.getCreateTime());
            // 5.获取可搜索的规格参数，key是参数名，值是参数值
            SpuDetailEntity detailEntity = spuDetailService.getById(spu.getId());
            //  5.1 获取特殊的规格参数
            //  k 为属性id   v为属性值
            Map<Long, Object> genericSpecMap = JSON.parseObject(detailEntity.getGenericSpec(), new TypeReference<Map<Long, Object>>() {});
            // 5.2 获取销售属性的规格参数
            Map<Long, List<Object>> specialSpecMap = JSON.parseObject(detailEntity.getSpecialSpec(), new TypeReference<Map<Long, List<Object>>>() {});
            // 获取该商品所属的三级分类关联的所有属性值
            List<SpecParamEntity> params = paramService.listByCid(spu.getCid3());
            // 5.3 定义集合接收数据
            List<Specs> specs = new ArrayList<>();
            params.forEach(param -> {
                Specs s = new Specs();
                // 判断是否通用规格参数
                if(param.getSearching() == 1L){   //判断属性是否可查询
                    if (param.getGeneric() == 1L) { // 判断是否为通用属性
                        // 获取通用规格参数值
                        String value = genericSpecMap.get(param.getId()).toString();
                        // 判断是否是数值类型
                        if (param.getNumeric() == 1L){
                            // 如果是数值的话，判断该数值落在那个区间
                            value = chooseSegment(value, param);
                        }
                        s.setSpecId(param.getId());
                        s.setSpecValue(value);
                        s.setSpecName(param.getName());
                    } else {
                        s.setSpecId(param.getId());
                        s.setSpecValue(JSON.toJSONString(specialSpecMap.get(param.getId())));
                        s.setSpecName(param.getName());
                    }
                }
                if(s.getSpecId() != null){
                    specs.add(s);
                }
            });
            goods.setSpecs(specs);
            // 6.设置商品的sku信息
            List<SkuEntity> infoBySpuId = skuService.getInfoBySpuId(spu.getId());
            List<Long> prices = new ArrayList<>();
            List<skuto> collect = infoBySpuId.stream().map(item -> {
                skuto sk = new skuto();
                BeanUtils.copyProperties(item, sk);
                prices.add(Long.parseLong(item.getPrice().toPlainString()));
                return sk;
            }).collect(Collectors.toList());
            //  设置sku集合的价格数组
            goods.setPrice(prices);
            // 将数据转为json保存
            goods.setSkus(JSON.toJSONString(collect));
            R r = goodsFeign.bulkIndex(goods);
            if(r.getCode() != 0){  //判断是否添加成功
                log.info("远程调用es批量存储服务出错了");
            }
        }
        // 修改商品的状态  上架还是下架
        if(saleable == SkuEnum.skuEnum.SKU_SALEABLE.getCode()){
            spuDao.SaveSaleable(SkuEnum.skuEnum.SKU_SALEABLE_OFF.getCode(),id);
        }else {
            spuDao.SaveSaleable(SkuEnum.skuEnum.SKU_SALEABLE.getCode(),id);
        }
    }

    private String chooseSegment(String value, SpecParamEntity p) {
        double val = NumberUtils.toDouble(value);
        String result = "其它";
        // 保存数值段
        for (String segment : p.getSegments().split(",")) {
            String[] segs = segment.split("-");
            // 获取数值范围
            double begin = NumberUtils.toDouble(segs[0]);
            double end = Double.MAX_VALUE;
            if(segs.length == 2){
                end = NumberUtils.toDouble(segs[1]);
            }
            // 判断是否在范围内
            if(val >= begin && val < end){
                if(segs.length == 1){
                    result = segs[0] + p.getUnit() + "以上";
                }else if(begin == 0){
                    result = segs[1] + p.getUnit() + "以下";
                }else{
                    result = segment + p.getUnit();
                }
                break;
            }
        }
        return result;
    }


    /**
     * 获取商品和品牌信息
     * @return
     */
    @Override
    public List<BrandAndProduct> getBrandAndProduct() {
        return spuDao.getBrandAndProduct();
    }

    @Override
    public void SaveGoods(GoodsVo goodsVo) {
        /**
         *   TODO 1. 根据修改spu信息 tb_spu
         *   TODO 2. 根据skuid库存信息 tb_stock
         *   TODO 3. 根据spuid修改商品描述信息  tb_spu_detail
         *   TODO 4. 修改 sku信息  tb_sku  可根据sPuid先删除在添加
         */

        //  1. 修改商品的spu信息
        SpuEntity spuInfo = new SpuEntity();
        BeanUtils.copyProperties(goodsVo,spuInfo);
        this.updateById(spuInfo);

        // 2. 修改商品描述信息  tb_spu_detail
        SpuDetailEntity spuDetail = goodsVo.getSpuDetail();
        spuDetail.setSpuId(goodsVo.getId());
        spuDetailService.updateById(spuDetail);

        // 根据spuid先删除sku信息
        List<SkuEntity> infoBySpuId = skuService.getInfoBySpuId(goodsVo.getId());
        List<Long> skuids = infoBySpuId.stream().map(item -> {
            return item.getId();
        }).collect(Collectors.toList());
        // 删除原来的sku信息
        Boolean flag = skuService.deleteSku(goodsVo.getId());
        // 删除原来的库存信息
        boolean b = stockService.removeByIds(skuids);
        if(flag && b){
            // 3. 在保存sku信息同时保存商品库存信息 tb_stock
            List<SkuVo> skus = goodsVo.getSkus();
            if(skus !=null && skus.size()>0){
                skus.forEach(item->{
                    //  保存sku信息
                    SkuEntity skuEntity = new SkuEntity();
                    BeanUtils.copyProperties(item,skuEntity);
                    skuEntity.setSpuId(spuInfo.getId());
                    //String price = item.getPrice().toString();
                    //price = price.substring(0,price.length()-2);
                   /// price = price+".00";
                    skuEntity.setPrice(item.getPrice());
                    skuService.save(skuEntity);
                    //  保存sku的库存信息
                    StockEntity stock = new StockEntity();
                    stock.setSkuId(skuEntity.getId());
                    stock.setStock(item.getStock());
                    stockService.save(stock);
                });
            }
       }
    }

    @Override
    public void addgoods(GoodsVo goodsVo) {

        /**
         *   TODO 1. 保存spu信息 tb_spu
         *   TODO 2. 保存库存信息 tb_stock
         *   TODO 3. 保存商品描述信息  tb_spu_detail
         *   TODO 4. 保存sku信息   tb_sku
         */
        //  1. 保存商品的spu信息
        SpuEntity spuInfo = new SpuEntity();
        BeanUtils.copyProperties(goodsVo,spuInfo);
        this.save(spuInfo);

        // 2. 保存商品描述信息  tb_spu_detail
        SpuDetailEntity spuDetail = goodsVo.getSpuDetail();
        spuDetail.setSpuId(spuInfo.getId());
        spuDetailService.save(spuDetail);

        // 3. 在保存sku信息同时保存商品库存信息 tb_stock
        List<SkuVo> skus = goodsVo.getSkus();
        if(skus !=null && skus.size()>0){
            skus.forEach(item->{
                //  保存sku信息
                SkuEntity skuEntity = new SkuEntity();
                BeanUtils.copyProperties(item,skuEntity);
                skuEntity.setSpuId(spuInfo.getId());
//                String price = item.getPrice().toString();
//                price = price.substring(0,price.length()-2);
//                price = price+".00";i
                skuEntity.setPrice(item.getPrice());
                skuService.save(skuEntity);
                //  保存sku的库存信息
                StockEntity stock = new StockEntity();
                stock.setSkuId(skuEntity.getId());
                stock.setStock(item.getStock());
                stockService.save(stock);
            });
        }

    }

    @Override
    public PageResult<SpuVo> getSpuPages(SpuPageParamVo paramVo) {
        QueryWrapper<SpuEntity> wrapper = new QueryWrapper<>();
        if(!StringUtils.isEmpty(paramVo.getKey())){
            wrapper.and(war->{
                war.like("title",paramVo.getKey()).or().like("sub_title",paramVo);
            });
        }
        if(paramVo.getSaleable()!= null) {
            if (paramVo.getSaleable()) {
                wrapper.eq("saleable", 1);
            } else {
                wrapper.eq("saleable", 0);
            }
        }

        //参数一是当前页，参数二是每页个数
        IPage<SpuEntity> spupage = new Page<>(paramVo.getPage(), paramVo.getRows());
        IPage<SpuEntity> iPage = baseMapper.selectPage(spupage, wrapper);
        List<SpuEntity> spuList = iPage.getRecords();
        List<SpuVo> spuVos = spuList.stream().map(item -> {
            SpuVo spuVo = new SpuVo();
            BeanUtils.copyProperties(item,spuVo);
            String cname = categoryService.getCategoryAllNameByid(item.getCid1(),item.getCid2(),item.getCid3());
            spuVo.setCname(cname);
            BrandEntity brandEntity = brandService.getById(item.getBrandId());
            spuVo.setBname(brandEntity.getName());
            return spuVo;
        }).collect(Collectors.toList());

        return new PageResult<>(iPage.getTotal(),spuVos);
    }
}